namespace SharePointImporter.CommandLine
{
    using System;
    using System.Globalization;
    using SharePoint.ImportExport.Core;
    
    /// <summary>
    /// This is the parameters class
    /// </summary>
    internal class Parameters
    {
        /// <summary>
        /// This is the directory name containing the struct.xml file
        /// </summary>
        private string directoryName = String.Empty;
        
        /// <summary>
        /// This is the URL to the site collection
        /// </summary>
        private string siteCollectionRootURL = String.Empty;
        
        /// <summary>
        /// This is the managed path to be used when importing
        /// </summary>
        private string managedPath = String.Empty;
        
        /// <summary>
        /// This is the Site name
        /// </summary>
        private string siteName = String.Empty;
        
        /// <summary>
        /// This controls whether or not if user information is imported
        /// </summary>
        private bool setSecurity = false;
        
        /// <summary>
        /// This contols if import to already existing sites is allowed
        /// </summary>
        private bool allowImportToExistingSites = false;
        
        /// <summary>
        /// This contols if import to already existing lists is allowed
        /// </summary>
        private bool allowImportToExistingLibraries = false;
        
        /// <summary>
        /// This contols if the xml schema will be validated
        /// </summary>
        private bool checkSchema = false;
        
        /// <summary>
        /// This specifies the error reporting threshold
        /// </summary>
        private ErrorLevel reportLevel = ErrorLevel.Information;

        /// <summary>
        /// Initializes a new instance of the Parameters class.
        /// </summary>
        public Parameters()
        {
        }
        
        /// <summary>
        /// Gets or sets the reporting level
        /// </summary>
        public ErrorLevel ReportLevel
        {
            get
            {
                return this.reportLevel;
            }

            set
            {
                this.reportLevel = value;
            }
        }

        /// <summary>
        /// Gets or sets the directory
        /// </summary>
        public string DirectoryName
        {
            get
            {
                return this.directoryName;
            }

            set
            {
                this.directoryName = value;
            }
        }

        /// <summary>
        /// Gets or sets the Site Collection URL
        /// </summary>
        public string SiteCollectionRootURL
        {
            get
            {
                return this.siteCollectionRootURL;
            }

            set
            {
                this.siteCollectionRootURL = value;
            }
        }
        
        /// <summary>
        /// Gets or sets the managed path
        /// </summary>
        public string ManagedPath
        {
            get
            {
                return this.managedPath;
            }

            set
            {
                this.managedPath = value;
            }
        }

        /// <summary>
        /// Gets or sets the Site name
        /// </summary>
        public string SiteName
        {
            get
            {
                return this.siteName;
            }

            set
            {
                this.siteName = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether or not security information will be imported
        /// </summary>
        public bool SetSecurity
        {
            get
            {
                return this.setSecurity;
            }

            set
            {
                this.setSecurity = value;
            }
        }

        /// <summary>
        ///  Gets or sets a value indicating whether or not the xml files will be validated
        /// </summary>
        public bool CheckSchema
        {
            get
            {
                return this.checkSchema;
            }

            set
            {
                this.checkSchema = value;
            }
        }
        
        /// <summary>
        ///  Gets or sets a value indicating whether or not importing to already existing sites is allowed
        /// </summary>
        public bool AllowImportToExistingSites
        {
            get
            {
                return this.allowImportToExistingSites;
            }

            set
            {
                this.allowImportToExistingSites = value;
            }
        }

        /// <summary>
        ///  Gets or sets a value indicating whether or not import to already existing list/libraries is allowed
        /// </summary>
        public bool AllowImportToExistingLibraries
        {
            get
            {
                return this.allowImportToExistingLibraries;
            }
            
            set
            {
                this.allowImportToExistingLibraries = value;
            }
        }

        /// <summary>
        /// This processes the arguments
        /// </summary>
        /// <param name="args">command line arguments</param>
        /// <param name="lastError">output string with error</param>
        /// <returns>true if succeeded</returns>
        public bool ProcessArgs(string[] args, out string lastError)
        {
            bool retValue = true;
            lastError = String.Empty;
            this.AllowImportToExistingSites = this.GetSingleArg(args, "-OKToImportToExistingSite");
            this.AllowImportToExistingLibraries = this.GetSingleArg(args, "-OKToImportToExistingLibrary");
            this.SetSecurity = this.GetSingleArg(args, "-ImportSecurity");
            this.CheckSchema = this.GetSingleArg(args, "-ValidateXML");
            string stringReportLevel = this.GetArg(args, "-reportLevel", String.Empty);
            if (stringReportLevel.Length > 0)
            {
                this.ReportLevel = (ErrorLevel)Enum.Parse(typeof(ErrorLevel), stringReportLevel);
            }

            this.SiteCollectionRootURL = this.GetArg(args, "-root", String.Empty);

            this.ManagedPath = this.GetArg(args, "-ManagedPath", String.Empty);
            this.SiteName = this.GetArg(args, "-SiteName", String.Empty);

            try
            {
                Uri uri = new Uri(this.SiteCollectionRootURL);

                if (String.IsNullOrEmpty(this.SiteName))
                {
                    SiteCollectionRootURL = uri.Scheme + "://" + uri.Host;
                    this.SiteName=uri.AbsolutePath;
                    if (!String.IsNullOrEmpty(this.ManagedPath))
                    {
                        int pos = this.SiteName.IndexOf(this.managedPath+"/");
                        if (pos > 0)
                        {
                            this.SiteName = this.SiteName.Substring(pos + this.managedPath.Length + 1 );
                        }
                    }
                }

            }
            catch (Exception Ex)
            {
                lastError = "The -root parameter must specify a valid URL: " + this.SiteCollectionRootURL;
                retValue = false;
            }

            if (this.SiteCollectionRootURL.Length < 1 && !this.CheckSchema)
            {
                lastError = "You must specify the -root parameter";
                retValue = false;
            }

            this.DirectoryName = this.GetArg(args, "-folder", String.Empty);
            if (this.DirectoryName.Length < 1)
            {
                lastError = "You must specify the -folder parameter";
                retValue = false;
            }

            return retValue;
        }

        /// <summary>
        /// This processes the arguments looking for a specific topic
        /// </summary>
        /// <param name="args">Command line arguments</param>
        /// <param name="token">token to look for</param>
        /// <param name="defaultValue">Default value to be retrieved if token not found</param>
        /// <returns>value of token or defaultvalue</returns>
        private string GetArg(string[] args, string token, string defaultValue)
        {
            string result = defaultValue;
            for (int i = 0; i < args.Length; i++)
            {
                if (0 == String.Compare(args[i], token, true, CultureInfo.InvariantCulture))
                {
                    result = args[i + 1];
                    break;
                }
            }

            return result;
        }

        /// <summary>
        /// Finds a single argument
        /// </summary>
        /// <param name="args">Command line arguments</param>
        /// <param name="token">Token to look for</param>
        /// <returns>true if found otherwise false</returns>
        private bool GetSingleArg(string[] args, string token)
        {
            for (int i = 0; i < args.Length; i++)
            {
                if (0 == String.Compare(args[i], token, StringComparison.OrdinalIgnoreCase))
                {
                    return true;
                }
            }

            return false;
        }
    }
}
